package com.zhou.base.components.bs.common.util.id;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * @author xianfeng
 * @date 2023/7/26 17:44
 */
public class TransNoUtil {
    public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");
    public static final String TRANS_KEY = "qinqing:pay:trans_idx";
    public static final String RESULT_NO_KEY = "qinqing:pay:res_no_idx";
    public static final String POLICY_NO_KEY = "qinqing:policy:res_no_idx";
    public static final String POLICY_INCR_KEY = "10000";
    public static final String PAY_SERIAL_NO_KEY = "qinqing:pay:pay_serial_no_idx";
    public static final String INCR_IDX_SCRIPT_CONTENT = "local idx = redis.call(\"incr\", KEYS[1])\n" +
            "if idx % tonumber(ARGV[1]) == 0 then\n" +
            "    redis.call(\"set\", KEYS[1], \"1\")\n" +
            "    return 1\n" +
            "end\n" +
            "return idx";

    public static final RedisScript<Long> INCR_IDX_SCRIPT = new DefaultRedisScript<>(INCR_IDX_SCRIPT_CONTENT,
            Long.class);

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 生成自增的序列号
     *
     * @return
     */
    public Long generateSeq(String key, Long maxSeq) {
        List<String> keys = ImmutableList.of(key);
        Long idx = stringRedisTemplate.execute(INCR_IDX_SCRIPT, keys, maxSeq + "");
        return idx;
    }

    /**
     * 生成订单号
     * 格式: 时间戳(精确到秒) + 自增循环序号(5位)
     *
     * @return
     */
    public String generateTransNo() {
        List<String> keys = ImmutableList.of(TRANS_KEY);
        Long idx = stringRedisTemplate.execute(INCR_IDX_SCRIPT, keys, "100000");
        Long timestamp = System.currentTimeMillis() / 1000;
        return timestamp + "" + String.format("%05d", idx);
    }

    /**
     * 生成认定结果序号
     * 格式: 日期(8位) + 秒(5位) + 政策id(5位) + 序列号(5位)
     * <p>
     * 目前没有对缓存key设置过期时间, 应该通过定时任务，生成将来7天的的key，设置过期时间，
     * 保障内存不会溢出。
     */
    public String generateResultNo(Long policyId) {
        Preconditions.checkNotNull(policyId, "政策id不能为空");
        List<String> keys = ImmutableList.of(RESULT_NO_KEY);
        Long idx = stringRedisTemplate.execute(INCR_IDX_SCRIPT, keys, "100000");
        String date = DATE_FORMATTER.format(LocalDate.now());
        String sec = String.format("%05d", LocalTime.now().toSecondOfDay());
        String pid = String.format("%05d", policyId);

        return date + sec + pid + String.format("%05d", idx);
    }

    public String generateStandPolicyCode() {
        StringBuffer buffer = new StringBuffer();
        String date = DATE_FORMATTER.format(LocalDate.now());
        buffer.append("GX");
        buffer.append(date);
        buffer.append("A");
        List<String> keys = ImmutableList.of(POLICY_NO_KEY);
        Long idx = stringRedisTemplate.execute(INCR_IDX_SCRIPT, keys, POLICY_INCR_KEY);
        int length = idx.toString().length();
        for (int i = 0; i < (POLICY_INCR_KEY.length() - length); i++) {
            buffer.append("0");
        }
        buffer.append(idx);
        buffer.append("V1");
        return buffer.toString();
    }

    public String generatePolicyCode() {
        StringBuffer buffer = new StringBuffer();
        String date = DATE_FORMATTER.format(LocalDate.now());
        buffer.append("GX");
        buffer.append(date);
        buffer.append("A");
        List<String> keys = ImmutableList.of(POLICY_NO_KEY);
        Long idx = stringRedisTemplate.execute(INCR_IDX_SCRIPT, keys, POLICY_INCR_KEY);
        int length = idx.toString().length();
        for (int i = 0; i < (POLICY_INCR_KEY.length() - length); i++) {
            buffer.append("0");
        }
        buffer.append(idx);
        buffer.append("V1");
        return buffer.toString();
    }

    public String generatePolicySubject() {
        StringBuffer buffer = new StringBuffer();
        String date = DATE_FORMATTER.format(LocalDate.now());
        buffer.append("ZT");
        buffer.append(date);
        buffer.append("A");
        List<String> keys = ImmutableList.of(POLICY_NO_KEY);
        Long idx = stringRedisTemplate.execute(INCR_IDX_SCRIPT, keys, POLICY_INCR_KEY);
        int length = idx.toString().length();
        for (int i = 0; i < (POLICY_INCR_KEY.length() - length); i++) {
            buffer.append("0");
        }
        buffer.append(idx);
        return buffer.toString();
    }

    /**
     * 生成兑付流水单号，格式：中心功能标识：“P”+日期（8位）+分隔符“A”+序列号（5位）
     * 目前没有对缓存key设置过期时间, 应该通过定时任务，生成将来7天的的key，设置过期时间，
     * * 保障内存不会溢出。
     */
    public String generatePaySerialNo() {
        List<String> keys = ImmutableList.of(PAY_SERIAL_NO_KEY);
        Long idx = stringRedisTemplate.execute(INCR_IDX_SCRIPT, keys, "100000");
        String date = DATE_FORMATTER.format(LocalDate.now());
        return "P" + date + "A" + String.format("%05d", idx);
    }

}
